//
//  Level3Layer.m
//
//  source file for third layer of the game
//

#import "LevelLayer.h"
#import "Level2Layer.h"
#import "Level3Layer.h"
#import "AppDelegate.h"
#import "MainMenuLayer.h"
#import "GameState.h"
#import "SimpleAudioEngine.h"

static const int kTimerLabelSize = 64;
static const int kHeightOffset = 94;
static const int kTotalDistractions = 10;
static const int kAllWantedObjects = 10;
static const int kTotalWantedObjects = 3;
static const int kDefaultTimer = 60;
static const int kWantedObject = 1;
static const int kUnWantedObject = 0;
static const int kMainMenuButton = 0;
static const int kRetryButton = 1;
static int pauseButton = 0;

@implementation Level3Layer

// returns a scene object containing the current layer
// this essentially loads the "screen" for a
// particular section or part of the game
+(CCScene *) scene
{
	CCScene *scene = [CCScene node];
    Level3Layer *layer = [Level3Layer node];
    
	[scene addChild: layer];
	
	return scene;
}

// implements the main game logic which is when the player
// touches an object, the score is adjusted based on whether
// the object touched is a wanted or unwanted object
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint location = [self convertTouchToNodeSpace:touch];
    
    // a list of screen objects to delete. this list is needed as opposed to
    // deleting straight from currentScreenObjects because objective-c does not
    // allow the mutation of a NSMutableArray while it is being enumerated (i.e. iterated over)
    NSMutableArray *screenObjectsToDelete = [[NSMutableArray alloc] init];
    
    // when a touch is registered, go through all the objects currently on screen
    // and if a wanted object is touched, add it to the list of objects to be removed from
    // the screen. if a distraction is touched, it will wiggle and resume its normal action
    for (CCSprite *screenObj in _currentScreenObjects) {
        if (CGRectContainsPoint(screenObj.boundingBox, location)) {
            if (screenObj.tag == kWantedObject) {
                [_scoreLabel setString:[NSString stringWithFormat:@"%d", [[GameState sharedGameState] incScore]]];
                [[SimpleAudioEngine sharedEngine] playEffect:@"146721__fins__menu-click.wav"];
                
                [screenObjectsToDelete addObject:screenObj];
                
            }
            else if (screenObj.tag == kUnWantedObject) {
                [_scoreLabel setString:[NSString stringWithFormat:@"%d", [[GameState sharedGameState] decScore]]];
                [screenObj runAction:[CCSequence actions:[CCRotateBy actionWithDuration:0.3 angle:20], [CCRotateBy actionWithDuration:0.3 angle:-40], [CCRotateBy actionWithDuration:0.3 angle:20], nil]];
                [[SimpleAudioEngine sharedEngine] playEffect:@"171526__fins__old-reactor.wav"];
            }
            
            // this tag assignment is needed to prevent the score from being
            // updated more than once
            screenObj.tag = 2;
        }
    }
    
    for (CCSprite *objToDelete in screenObjectsToDelete) {
        
        // before an object disappears from screen, show a quick animation of it
        // moving slightly up and then down
        CCMoveTo * moveUp = [CCMoveTo actionWithDuration:0.2
                                                position:ccp(objToDelete.position.x, objToDelete.position.y + 20)];
        
        CCMoveTo * moveDown = [CCMoveTo actionWithDuration:0.5
                                                  position:ccp(objToDelete.position.x, 0)];
        
        CCCallBlockN * actionMoveDone = [CCCallBlockN actionWithBlock:^(CCNode *node) {
            [_currentScreenObjects removeObject:objToDelete];
            [node removeFromParentAndCleanup:YES];
        }];
        
        [objToDelete runAction:[CCSequence actions:moveUp, moveDown, actionMoveDone, nil]];
    }
    
    [screenObjectsToDelete release];
}

// this is the method that handles the button press functionality of the alert box
// that pops up when the game ends or when the user progresses to the next level
-(void) alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    [[CCDirector sharedDirector] resume];
    
    // the user presses the first button main menu which aborts the game
    // the score and data from that game are saved
    if (buttonIndex == kMainMenuButton) {
        [[GameState sharedGameState] setState:@"totalScore" value:[[GameState sharedGameState] getScore]+[[[GameState sharedGameState] getState:@"totalScore"] integerValue]];
        [[GameState sharedGameState] setState:@"totalGamesPlayed" value:1+[[[GameState sharedGameState] getState:@"totalGamesPlayed"] integerValue]];
        [[GameState sharedGameState] saveHighestScore];
        [[GameState sharedGameState] resetScore];
        [[GameState sharedGameState] resetCompletion];
        [[CCDirector sharedDirector] replaceScene:[MainMenuLayer scene]];
    }
    // the user presses the second button, and no time is remaining,
    // implies the user has lost the game, the score and data are saved
    else if (buttonIndex == kRetryButton && _currentTime == 0) {
        [[GameState sharedGameState] setState:@"totalScore" value:[[GameState sharedGameState] getScore]+[[[GameState sharedGameState] getState:@"totalScore"] integerValue]];
        [[GameState sharedGameState] setState:@"totalGamesPlayed" value:1+[[[GameState sharedGameState] getState:@"totalGamesPlayed"] integerValue]];
        [[GameState sharedGameState] saveHighestScore];
        [[GameState sharedGameState] resetScore];
        [[GameState sharedGameState] resetCompletion];
        [[CCDirector sharedDirector] replaceScene:[LevelLayer scene]];
    }
    // the user presses the second button with time remaining
    // implies that the user wants to resume the game
    else if (buttonIndex == kRetryButton && _currentTime != 0 && pauseButton != 0){
        pauseButton = 0;
    }
    // the user presses the second button with time remaining, implies that
    // the user has the required amount of points and wants to progress to next level
    else if (buttonIndex == kRetryButton && _currentTime != 0) {
        [[GameState sharedGameState] incCompletion];
        [[CCDirector sharedDirector] replaceScene:[LevelLayer scene]];
    }
}

// this method is called every 1 second to update the amount of
// time left for this level
-(void) gameTimer
{
    [_timeLabel setString:[NSString stringWithFormat:@"%d", --_currentTime]];
    
    if (_currentTime == 0) {
        [[CCDirector sharedDirector] pause];
        [[GameState sharedGameState] setState:@"totalTimePlayed" value:60+[[[GameState sharedGameState] getState:@"totalTimePlayed"] integerValue]];
        UIAlertView *dialog = [[UIAlertView alloc] init];
        [dialog setDelegate:self];
        [dialog setTitle:@"Times Up!"];
        [dialog setMessage:[NSString stringWithFormat:@"Your high score is: %d", [[GameState sharedGameState] getScore]]];
        [dialog addButtonWithTitle:@"Main Menu"];
        [dialog addButtonWithTitle:@"Retry"];
        [dialog show];
        [dialog release];
    }
}

// this method is called every tenth of a second to check if 5 points has been
// accumulated in this level, in which case the player moves on to the next level
-(void) scoreCheck
{
    if ([[GameState sharedGameState] getScore] == 5*([[GameState sharedGameState] getCompletion] + 1)) {
        [[CCDirector sharedDirector] pause];
        
        // check if the time taken to complete this level is a record best
        // time for the user, if so, update the best time
        int bestTime = [[[GameState sharedGameState] getState:@"level3BestTime"] integerValue];
        if (60-_currentTime < bestTime) {
            [[GameState sharedGameState] setState:@"level3BestTime" value:60-_currentTime];
        }
        
        // adds the time taken to complete this level to the total time played
        [[GameState sharedGameState] setState:@"totalTimePlayed" value:60-_currentTime+[[[GameState sharedGameState] getState:@"totalTimePlayed"] integerValue]];
        
        UIAlertView *dialog = [[UIAlertView alloc] init];
        [dialog setDelegate:self];
        [dialog setTitle:@"Congratulations!"];
        [dialog setMessage:[NSString stringWithFormat:@"You've reached the next level!"]];
        [dialog addButtonWithTitle:@"Main Menu"];
        [dialog addButtonWithTitle:@"Continue"];
        [dialog show];
        [dialog release];
    }
}

-(void)pausePressed
{
    pauseButton = 1;
    [[CCDirector sharedDirector] pause];
    UIAlertView *dialog = [[UIAlertView alloc] init];
    [dialog setDelegate:self];
    [dialog setTitle:@"Level 3"];
    [dialog setMessage:[NSString stringWithFormat:@"You have paused the game"]];
    [dialog addButtonWithTitle:@"Main Menu"];
    [dialog addButtonWithTitle:@"Resume"];
    [dialog show];
    [dialog release];
    
    
    
    
}

// this method is called to add a pen box to be tapped by the player
-(void) addLevelObjects
{
    CGSize winSize = [[CCDirector sharedDirector] winSize];
    
    // initialize the pen box
    CCSprite *box = [CCSprite spriteWithFile:@"crayonbox.png"];
    box.position = ccp(-box.contentSize.width / 2, winSize.height/2);
    [_currentScreenObjects addObject:box];
    [self addChild:box z:1];
    
    NSMutableArray *penList = [[NSMutableArray alloc] init];
    NSMutableArray *brokenPenList = [[NSMutableArray alloc] init];
    
    // choose the colours of the pens that will appear in this box
    int penChoiceCount = 0;
    while (penChoiceCount < 5){
        int randNum = arc4random() % kAllWantedObjects;
        NSString *randomPick = [_distractionObjects objectAtIndex:(randNum)];
        NSString *randomBrokenPick = [_allWantedObjects objectAtIndex:(randNum)];
        if ([penList containsObject:randomPick]){
            continue;
        }
        else{
            [penList addObject:randomPick];
            [brokenPenList addObject:randomBrokenPick];
            penChoiceCount++;
        }
    }
    
    // initialize the list of pen images to be displayed
    NSMutableArray *pens = [[NSMutableArray alloc] init];
    for(int i=0; i < 5; i++){
        CCSprite *pen = [CCSprite spriteWithFile:[penList objectAtIndex:(i)]];
        [pens addObject:pen];
    }
    
    int defectChance = arc4random() % 2;
    
    // randomly determine if next object is defected
    if (defectChance == 1){
        int defectLocation = arc4random() % 5;
        int defectType = arc4random() % 3;
        
        if (defectType == 0){ // broken pen case: replace a pen with a broken one
            [pens replaceObjectAtIndex:defectLocation withObject:[CCSprite spriteWithFile:[brokenPenList objectAtIndex:(defectLocation)]]];
        }
        else if (defectType == 1){ // missing pen case: replace a pen with a blank image
            [pens replaceObjectAtIndex:defectLocation withObject:[CCSprite spriteWithFile:@"blankcrayon.png"]];
        }
        else{ // duplicate pen case
            int duplicatePick = defectLocation;
            while(duplicatePick == defectLocation){
                duplicatePick = arc4random() % 5;
            }
            [pens replaceObjectAtIndex:defectLocation withObject:[CCSprite spriteWithFile:[penList objectAtIndex:(duplicatePick)]]];
        }
    
        box.tag = 1;
        
    }
    else{
        
        box.tag = 0;
        
    }
    
    // add the images to the box
    int counter = 0;
    for (CCSprite *pen in pens) {
        pen.position = ccp(counter++*20+37,70);
        [box addChild:pen];
    }
    
    float screenDuration = (3.0-0.3*floor([[GameState sharedGameState] getCompletion]/3));
    if (screenDuration < 0.6){
        screenDuration = 0.6;
    }    
    
    CCMoveTo * actionMoveRight = [CCMoveTo actionWithDuration:screenDuration
                                                     position:ccp(winSize.width + box.contentSize.width / 2, winSize.height/2)];
    
    CCCallBlockN * actionMoveDone = [CCCallBlockN actionWithBlock:^(CCNode *node) {
        [_currentScreenObjects removeObject:box];
        [node removeFromParentAndCleanup:YES];
    }];
    
    [box runAction:[CCSequence actions:actionMoveRight, actionMoveDone, nil]];
    
    // deallocate memory used in this function
    [pens release];
    [penList release];
    [brokenPenList release];
}

// initialize this layer; this includes initializing several instance variables
// and initializing the sprites needed for this scene
-(id) init
{
	if( (self = [super init]) ) {
        
        // list of all images that we have for this level
        _distractionObjects = [[NSArray arrayWithObjects:@"browncrayon.png",@"bluecrayon.png",@"graycrayon.png",@"greencrayon.png",@"orangecrayon.png",@"indigocrayon.png",@"pinkcrayon.png",@"redcrayon.png",@"purplecrayon.png",@"yellowcrayon.png", nil] retain];
        _allWantedObjects = [[NSArray arrayWithObjects:@"brokenbrowncrayon.png",@"brokenbluecrayon.png",@"brokengraycrayon.png",@"brokengreencrayon.png",@"brokenorangecrayon.png",@"brokenindigocrayon.png",@"brokenpinkcrayon.png",@"brokenredcrayon.png",@"brokenpurplecrayon.png",@"yellowcrayon.png", nil] retain];
        
        _currentScreenObjects = [[NSMutableArray alloc] init];
        _wantedObjects = [[NSArray arrayWithObjects:@"duplicate_icon.png", @"missingicon.png", @"broken_icon.png", nil] retain];
        
        CGSize winSize = [[CCDirector sharedDirector] winSize];
        int posMultiplier = 1;
        int wantedPosX;
        int wantedPosY;
        
        // randomly populate the list of wanted objects until there are three elements in total.
        //while(_wantedObjects.count != kTotalWantedObjects) {
          //  NSString *randomPick = [_allWantedObjects objectAtIndex:(arc4random() % kAllWantedObjects)];
            
            //if ([_wantedObjects containsObject:randomPick]) {
              //  continue;
            //}
            //else {
              //  [_wantedObjects addObject:randomPick];
            //}
        //}
        
        // after each pick, display the object at the bottom of the screen
        for ( int i=1; i < kTotalWantedObjects+1; i++) {
            CCSprite *wantedSprite = [CCSprite spriteWithFile:[_wantedObjects objectAtIndex:(i-1)]];
            wantedPosX = winSize.width/2 + 200 * (posMultiplier-(kTotalWantedObjects+1)/2);
            wantedPosY = 70;
            wantedSprite.position = ccp( wantedPosX, wantedPosY);
            ++posMultiplier;
            [self addChild:wantedSprite z:1];
        }
        
        CCSprite *bg = [CCSprite spriteWithFile:@"level3background.png"];
        bg.position = ccp(winSize.width / 2, winSize.height / 2);
        [self addChild:bg z:0];
        
        _currentTime = kDefaultTimer;
        _timeLabel = [CCLabelTTF labelWithString:[NSString stringWithFormat:@"%d", kDefaultTimer] fontName:@"Marker Felt" fontSize:kTimerLabelSize];
		_timeLabel.position =  ccp(winSize.width - kTimerLabelSize, winSize.height - kTimerLabelSize);
        _timeLabel.color = ccc3(0, 0, 0);
		[self addChild: _timeLabel];
        
        _scoreLabel = [CCLabelTTF labelWithString:[NSString stringWithFormat:@"%d", [[GameState sharedGameState] getScore]] fontName:@"Marker Felt" fontSize:kTimerLabelSize];
        _scoreLabel.position = ccp(kTimerLabelSize / 2, winSize.height - kTimerLabelSize);
        _scoreLabel.color = ccc3(0, 0, 255);
        [self addChild: _scoreLabel];
        
        CCMenuItemImage *pauseBtn = [CCMenuItemImage itemWithNormalImage:@"pausebutton.png"
                                                           selectedImage:@"pausebutton.png" target:self selector:@selector(pausePressed)];
        
        //the pause button will be placed on the bottom right of the screen
        CCMenu *pauseMenu = [CCMenu menuWithItems:pauseBtn, nil];
        
        pauseMenu.position = ccp(950, 62.5);
        
        [self addChild:pauseMenu];
        
        self.touchEnabled = YES;
        [self schedule:@selector(gameTimer) interval:1.0];
        [self schedule:@selector(scoreCheck)];
        [self schedule:@selector(addLevelObjects) interval:2.0];
	}
    
	return self;
}

// deallocate all memory used
- (void) dealloc
{
    [_distractionObjects release];
    [_wantedObjects release];
    [_currentScreenObjects release];
    _distractionObjects = nil;
    _wantedObjects = nil;
    _currentScreenObjects = nil;
	[super dealloc];
}

#pragma mark GameKit delegate

@end